from typing import Optional
from fastapi import Depends, FastAPI, HTTPException
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import ORJSONResponse, PlainTextResponse
from starlette.requests import Request
from starlette.responses import PlainTextResponse, JSONResponse
from starlette.status import HTTP_400_BAD_REQUEST, HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN, \
    HTTP_422_UNPROCESSABLE_ENTITY
from ..utils.resp_util import GenericResp, GenericJSONResponse
from .enums.resp_enum import ErrTypes

import logging

logger = logging.getLogger(__name__)

class UnicornException(Exception):
    def __init__(self, name: str):
        self.name = name

class UnAuthException(Exception):
    def __init__(self, 
                 error_type: ErrTypes,
                 status_code: int = 403,
                 message: str = None
                 ):
        self.error_type = error_type
        self.status_code = status_code
        self.message = message

class GenericException(Exception):
    data: Optional[any] = None
    def __init__(self, 
                 error_type: ErrTypes = ErrTypes.unknown_error,
                 status_code: int = 200,
                 message: str = None,
                 data: Optional[any] = None
                 ):
        self.error_type = error_type
        self.status_code = status_code
        self.message = message or error_type.value[1]
        if data:
            self.data = data
        #print('Error: %s' % message)

class CustomHttpException(Exception):
    def __init__(self, 
                 error_type: ErrTypes = ErrTypes.unknown_error,
                 status_code: int = 200,
                 message: str = None
                 ):
        self.error_type = error_type
        self.status_code = status_code
        self.message = message or error_type.value[1]

class ErrorException(Exception):
    def __init__(self, name: str):
        self.name = name


async def error_exception_handler(request: Request, exc: ErrorException):
    x = exc.errors()
    return JSONResponse(
        status_code=511,
        content={"detail": jsonable_encoder(exc.errors())},
    )

class HttpErrorException(HTTPException):
    def __init__(self, name: str):
        self.name = name


async def generic_exception_handler(request: Request, exc: GenericException):
    """
    捕捉通用报错并进行自定义处理
    :param request:
    :param exc:
    :return:
    """
    print('>> generic_exception_handler')
    gresp = GenericResp(
        status_code=exc.status_code, # http响应码
        code=exc.error_type.value[0], 
        message=exc.message or exc.error_type.value[1],
        data=exc.data
    )
    return gresp.get_response()

async def custom_http_exception_handler(request: Request, exc: HTTPException):
    """
    捕捉Http报错并进行自定义处理
    :param request:
    :param exc:
    :return:
    """
    print('>> custom_http_exception_handler')
    #x = exc.errors()
    #error = jsonable_encoder(exc.errors())
    err_type = ErrTypes.http_error
    if exc.status_code == 400:
        err_type = ErrTypes.http_bad_request
    elif exc.status_code == 401:
        err_type = ErrTypes.http_unauthorized
    elif exc.status_code == 403:
        err_type = ErrTypes.http_forbidden
    elif exc.status_code == 404:
        err_type = ErrTypes.http_notfound
    elif exc.status_code == 405:
        err_type = ErrTypes.http_method_not_allowed
    #error = exc.detail
    resp = GenericResp(
        status_code=exc.status_code,
        code=err_type.value[0], 
        message= err_type.value[1]
    ).get_response()
    return resp


async def bad_request_exception_handler(request: Request, exc: HTTPException):
    """
    捕捉400报错并进行自定义处理
    :param request:
    :param exc:
    :return:
    """
    print('>> bad_request_exception_handler')
    #x = exc.errors()
    #error = jsonable_encoder(exc.errors())
    error = exc.detail
    resp = GenericResp(
        status_code = HTTP_400_BAD_REQUEST, 
        code=ErrTypes.forbidden_error.value[0], 
        message=ErrTypes.forbidden_error.value[1]
    ).get_response()
    return resp

async def forbidden_request_exception_handler(
        request: Request, exc: HTTPException
    ) -> GenericJSONResponse:
    """
    捕捉403报错并进行自定义处理
    :param request:
    :param exc:
    :return:
    """
    print('>> forbidden_request_exception_handler')
    #x = exc.errors()
    #error = jsonable_encoder(exc.errors())
    error = exc.detail
    resp = GenericResp(
        status_code = HTTP_403_FORBIDDEN, 
        code=ErrTypes.forbidden_error.value[0], 
        message=ErrTypes.forbidden_error.value[1]
    ).get_response()
    return resp


async def my_request_validation_exception_handler(
    request: Request, exc: RequestValidationError) -> JSONResponse:
    return JSONResponse(
        status_code=HTTP_422_UNPROCESSABLE_ENTITY,
        content={"detail1": jsonable_encoder(exc.errors())},
    )


async def request_validation_exception_handler(
        request: Request, exc: RequestValidationError
#) -> JSONResponse:
) -> GenericJSONResponse:
    """
    捕捉422报错并进行自定义处理
    :param request:
    :param exc:
    :return:
    """
    print('>> request_validation_exception_handler')
    logger.error(exc.errors())
    #x = exc.errors()
    #error = jsonable_encoder(exc.errors())
    resp = GenericResp(
        status_code=HTTP_422_UNPROCESSABLE_ENTITY, # 422
        code=ErrTypes.validation_error.value[0], 
        message=ErrTypes.validation_error.value[1]
    ).get_response()
    return resp
    '''
    return JSONResponse(
        status_code=HTTP_422_UNPROCESSABLE_ENTITY,
        content=resp,
    )
    '''
    
    


